<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.4.0">


  <link rel="apple-touch-icon" sizes="180x180" href="/myblog/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/myblog/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/myblog/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/myblog/images/logo.svg" color="#222">

<link rel="stylesheet" href="/myblog/css/main.css">



<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.4/css/all.min.css" integrity="sha256-mUZM63G8m73Mcidfrv5E+Y61y7a12O5mW4ezU3bxqW4=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/animate.css@3.1.1/animate.min.css" integrity="sha256-PR7ttpcvz8qrF57fur/yAx1qXMFJeJFiA6pSzWi0OIE=" crossorigin="anonymous">

<script class="next-config" data-name="main" type="application/json">{"hostname":"gitee.com","root":"/myblog/","images":"/myblog/images","scheme":"Gemini","darkmode":false,"version":"8.8.0","exturl":false,"sidebar":{"position":"left","display":"always","padding":18,"offset":12},"copycode":false,"bookmark":{"enable":false,"color":"#222","save":"auto"},"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"stickytabs":false,"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果：${query}","hits_time":"找到 ${hits} 个搜索结果（用时 ${time} 毫秒）","hits":"找到 ${hits} 个搜索结果"}}</script><script src="/myblog/js/config.js"></script>
<meta name="description" content="live and love">
<meta property="og:type" content="website">
<meta property="og:title" content="矿小测的博客">
<meta property="og:url" content="https://gitee.com/cmygis/index.html">
<meta property="og:site_name" content="矿小测的博客">
<meta property="og:description" content="live and love">
<meta property="og:locale" content="zh_CN">
<meta property="article:author" content="矿小测">
<meta name="twitter:card" content="summary">


<link rel="canonical" href="https://gitee.com/cmygis/">



<script class="next-config" data-name="page" type="application/json">{"sidebar":"","isHome":true,"isPost":false,"lang":"zh-CN","comments":"","permalink":"","path":"index.html","title":""}</script>

<script class="next-config" data-name="calendar" type="application/json">""</script>
<title>矿小测的博客</title>
  




  <noscript>
    <link rel="stylesheet" href="/myblog/css/noscript.css">
  </noscript>
</head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏" role="button">
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/myblog/" class="brand" rel="start">
      <i class="logo-line"></i>
      <h1 class="site-title">矿小测的博客</h1>
      <i class="logo-line"></i>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>



<nav class="site-nav">
  <ul class="main-menu menu">
        <li class="menu-item menu-item-home"><a href="/myblog/" rel="section"><i class="home                          //首页 fa-fw"></i>首页</a></li>
        <li class="menu-item menu-item-archives"><a href="/myblog/archives/" rel="section"><i class="archive          //归档 fa-fw"></i>归档</a></li>
        <li class="menu-item menu-item-categories"><a href="/myblog/categories/" rel="section"><i class="th           //分类 fa-fw"></i>分类</a></li>
        <li class="menu-item menu-item-tags"><a href="/myblog/tags/" rel="section"><i class="tags                     //标签 fa-fw"></i>标签</a></li>
        <li class="menu-item menu-item-about"><a href="/myblog/about/" rel="section"><i class="user                   //关于 fa-fw"></i>关于</a></li>
  </ul>
</nav>




</div>
        
  
  <div class="toggle sidebar-toggle" role="button">
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
  </div>

  <aside class="sidebar">

    <div class="sidebar-inner sidebar-overview-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <div class="post-toc-wrap sidebar-panel">
        </div>
        <!--/noindex-->

        <div class="site-overview-wrap sidebar-panel">
          <div class="site-author site-overview-item animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">矿小测</p>
  <div class="site-description" itemprop="description">live and love</div>
</div>
<div class="site-state-wrap site-overview-item animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
        <a href="/myblog/archives/">
          <span class="site-state-item-count">4</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
          <a href="/myblog/categories/">
        <span class="site-state-item-count">1</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
          <a href="/myblog/tags/">
        <span class="site-state-item-count">2</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>



        </div>
      </div>
    </div>
  </aside>
  <div class="sidebar-dimmer"></div>


    </header>

    
  <div class="back-to-top" role="button" aria-label="返回顶部">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


    <div class="main-inner index posts-expand">

    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="https://gitee.com/cmygis/2021/10/31/%E9%9D%A2%E8%AF%95%E9%A2%98%E7%9B%AE%E6%B1%87%E6%80%BB/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/myblog/images/avatar.gif">
      <meta itemprop="name" content="矿小测">
      <meta itemprop="description" content="live and love">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="矿小测的博客">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/myblog/2021/10/31/%E9%9D%A2%E8%AF%95%E9%A2%98%E7%9B%AE%E6%B1%87%E6%80%BB/" class="post-title-link" itemprop="url">面试题目汇总</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>
      

      <time title="创建时间：2021-10-31 23:50:30 / 修改时间：23:50:18" itemprop="dateCreated datePublished" datetime="2021-10-31T23:50:30+08:00">2021-10-31</time>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h2 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h2><h3 id="操作系统中的heap和stack的区别"><a href="#操作系统中的heap和stack的区别" class="headerlink" title="操作系统中的heap和stack的区别"></a>操作系统中的heap和stack的区别</h3><p>堆栈是两种数据结构，是一种数据项按序排列的数据结构，只能在一端进行插入和删除操作。堆为队列优先，先进先出(FIFO)。栈为先进后出(FILO)。</p>
<p><strong>堆</strong> (操作系统):一般由程序员分配释放，如果程序员不释放，程序结束时可能由OS回收，分配方式类似于链表。注：java中都是系统GC，程序员无法进行GC。</p>
<p><strong>栈</strong> (操作系统)：由操作系统自动分配释放，存放函数的参数值，局部变量值等。操作方式与数据结构中的栈类似。</p>
<p>二、缓存方式</p>
<p>  1.堆：使用二级缓存，生命周期与虚拟机的GC算法有关（并不是引用为空就立即被GC），调用速度相对较低。</p>
<p>  2.栈：使用一级缓存，被调用时通常处于存储空间中，调用后被立即释放。</p>
<p><strong>java中堆栈的区别</strong></p>
<p>栈(stack)与堆(heap)都是Java用来在RAM中存放数据的地方。与C++不同，Java自动管理栈和堆，程序员不能直接地设置栈或堆。<br>　　在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。当在一段代码块定义一个变量时，Java就在栈中为这个变量分配内存空间，当超过变量的作用域后，Java会自动释放掉为该变量所分配的内存空间，该内存空间可以立即被另作他用。<br>　　堆内存用来存放由new创建的对象和数组，在堆中分配的内存，由Java虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或对象后，还可以在栈中定义一个特殊的变量，让栈中这个变量的取值等于数组或对象在堆内存中的首地址，栈中的这个变量就成了数组或对象的引用变量。引用变量就相当于是为数组或对象起的一个名称，以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。 </p>
<p><strong>Java中变量在内存中的分配</strong>：<br>　　1、类变量（static修饰的变量）：在程序加载时系统就为它在堆中开辟了内存，堆中的内存地址存放于栈以便于高速访问。静态变量的生命周期–一直持续到整个”系统”关闭。<br>　　2、实例变量：当你使用java关键字new的时候，系统在堆中开辟并不一定是连续的空间分配给变量（比如说类实例），然后根据零散的堆内存地址，通过哈希算法换算为一长串数字以表征这个变量在堆中的”物理位置”。 实例变量的生命周期–当实例变量的引用丢失后，将被GC（垃圾回收器）列入可回收“名单”中，但并不是马上就释放堆中内存。<br>　　3、局部变量：局部变量，由声明在某方法，或某代码段里（比如for循环），执行到它的时候在栈中开辟内存，当局部变量一但脱离作用域，内存立即释放。<br>————————————————<br>原文链接：<a target="_blank" rel="noopener" href="https://blog.csdn.net/BlackPlus28/article/details/81627082">https://blog.csdn.net/BlackPlus28/article/details/81627082</a></p>
<h3 id="什么是基于注解的切面实现"><a href="#什么是基于注解的切面实现" class="headerlink" title="什么是基于注解的切面实现"></a>什么是基于注解的切面实现</h3><p>AOP(面向切面编程)：在程序运行时，动态的将代码切入到类的指定方法、指定位置上的编程思想就是面向切面编程。</p>
<ul>
<li>切面：切入到指定类指定方法的代码片段</li>
<li>切入点：切入的那些类和方法成为切入点</li>
</ul>
<ul>
<li><p>AOP就是OOP的补充而已。OOP从横向上区分出一个个类来，而AOP则从纵向上向对象加入特定的代码。有了AOP，OOP变得立体了，如果加上时间维度，AOP使OOP从二维变成三维。</p>
</li>
<li><p>从技术上来说，AOP基本上是通过代理机制实现的。</p>
</li>
<li><p>经典的Spring AOP是基于动态代理技术的。在实现方式上，最常用的是实现MethodInterceptor接口来提供环绕通知，创建若干代理，然后使用ProxyBeanFactory配置工厂Bean，生成拦截器链，完成拦截。</p>
</li>
<li><p>我们通常使用注解的形式使用AOP</p>
<ul>
<li>在xml中的配置<ul>
<li>&lt;context:component-scan base-package=”demo.spring”/&gt;</li>
<li>&lt;aop:aspectj-autoproxy /&gt;</li>
</ul>
</li>
<li> context:component-scan，使用@Component自动发布bean，需要配置这个元素</li>
<li>aop:aspectj-autoproxy，使用@AspectJ及其它AOP注解需要配置，否则无法使用注解；@AspectJ注解，将@Component自动发布出来的”interceptor” bean转换为一个aspectj切面，而@Pointcut、@Before、@After、@Around等注解，功能与在xml文件中配置是一样的；@Pointcut注解下面的方法内容无意义，只是要求一个相应方法提供注解依附。</li>
<li>注解只能使用在能活的源码的场景，如果不能获取源码，则只能通过xml配置的形式，将制定的对象配置成拦截器，对指定目标进行拦截；因此，通过xml文件配置，而不是注解，是更加通用的方式。</li>
<li>除基础的springframework框架的jar外，还需要依赖cglib、aspectj的jar包，maven配置如下：</li>
</ul>
<p>总结：Spring实现AOP，动态代理技术的两种实现是jdk动态代理、cglib代理，根据被通知的方法是否为接口方法，来选择使用哪种代理生成策略。</p>
<ul>
<li>jdk动态代理：原理是实现接口的实例，拦截定于接口中的目标方法，，性能更优，是spring生成代理的优先选择。</li>
<li>cglib代理：原理是使用cglib库中的字节码动态生成技术，生成被代理类的子类实例，可以拦截代理类中的任一public方法的调用，无论目标方法是否定义与接口中，更通用，但性能相对jdk代理差一些。</li>
<li>原文：<a target="_blank" rel="noopener" href="https://www.cnblogs.com/songanwei/p/9386462.html">https://www.cnblogs.com/songanwei/p/9386462.html</a></li>
</ul>
</li>
</ul>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="https://gitee.com/cmygis/2021/10/31/%E6%94%B6%E8%97%8F%E7%9A%84%E7%AB%99%E7%82%B9/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/myblog/images/avatar.gif">
      <meta itemprop="name" content="矿小测">
      <meta itemprop="description" content="live and love">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="矿小测的博客">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/myblog/2021/10/31/%E6%94%B6%E8%97%8F%E7%9A%84%E7%AB%99%E7%82%B9/" class="post-title-link" itemprop="url">收藏的站点</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>
      

      <time title="创建时间：2021-10-31 22:55:45 / 修改时间：23:08:43" itemprop="dateCreated datePublished" datetime="2021-10-31T22:55:45+08:00">2021-10-31</time>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h2 id="技术博客"><a href="#技术博客" class="headerlink" title="技术博客"></a>技术博客</h2><h3 id="java"><a href="#java" class="headerlink" title="java"></a>java</h3><p><a target="_blank" rel="noopener" href="https://blog.searchinfogo.com/2019/04/18/interview-experience/">https://blog.searchinfogo.com/2019/04/18/interview-experience/</a></p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="https://gitee.com/cmygis/2021/10/31/%E6%9C%AC%E5%8D%9A%E5%AE%A2%E5%8F%82%E8%80%83%E5%86%85%E5%AE%B9/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/myblog/images/avatar.gif">
      <meta itemprop="name" content="矿小测">
      <meta itemprop="description" content="live and love">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="矿小测的博客">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/myblog/2021/10/31/%E6%9C%AC%E5%8D%9A%E5%AE%A2%E5%8F%82%E8%80%83%E5%86%85%E5%AE%B9/" class="post-title-link" itemprop="url">本博客参考内容</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>
      

      <time title="创建时间：2021-10-31 21:28:16 / 修改时间：22:16:02" itemprop="dateCreated datePublished" datetime="2021-10-31T21:28:16+08:00">2021-10-31</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/myblog/categories/%E6%97%A5%E5%B8%B8/" itemprop="url" rel="index"><span itemprop="name">日常</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h2 id="安装软件"><a href="#安装软件" class="headerlink" title="安装软件"></a>安装软件</h2><p>需要安装的软件有git、typora、node.js、cnpm，网上教程比较多，安装过程没有遇到问题，不做介绍。</p>
<h2 id="安装hexo博客环境"><a href="#安装hexo博客环境" class="headerlink" title="安装hexo博客环境"></a>安装hexo博客环境</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> 在cmd上或terminal执行下面命令</span></span><br><span class="line">cnpm install -g hexo-cli</span><br><span class="line"><span class="meta">#</span><span class="bash"> 安装完成后,查看hexo的版本</span></span><br><span class="line">hexo -v</span><br><span class="line"><span class="meta">#</span><span class="bash"> 构建自己的博客环境，进入博客文件夹</span></span><br><span class="line">hexo init</span><br><span class="line"><span class="meta">#</span><span class="bash"> 本地运行博客，地址localhost:4000</span></span><br><span class="line">hexo s</span><br></pre></td></tr></table></figure>

<h2 id="hexo常用命令"><a href="#hexo常用命令" class="headerlink" title="hexo常用命令"></a>hexo常用命令</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> 本地启动博客</span></span><br><span class="line">hexo s</span><br><span class="line"><span class="meta">#</span><span class="bash"> 新建博客文章，在<span class="built_in">source</span>/_posts文件夹</span></span><br><span class="line">hexo new &#x27;标题&#x27;</span><br><span class="line"><span class="meta">#</span><span class="bash"> 清除博客缓存</span></span><br><span class="line">hexo clean</span><br><span class="line"><span class="meta">#</span><span class="bash"> 将md文件生成静态页面</span></span><br><span class="line">hexo g</span><br></pre></td></tr></table></figure>

<h2 id="使用gitee托管博客"><a href="#使用gitee托管博客" class="headerlink" title="使用gitee托管博客"></a>使用gitee托管博客</h2><p>github国内访问速度不佳，故使用gitee pages发布博客</p>
<p>gitee pages现在需要上传身份证审核个人身份，一天即可审核通过。</p>
<ol>
<li><p>注册码云gitee账户</p>
</li>
<li><p>新建仓库</p>
</li>
<li><p>安装git插件</p>
</li>
</ol>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cnpm install --save hexo-deployer-git</span><br></pre></td></tr></table></figure>

<ol start="4">
<li>本地配置远程仓库</li>
</ol>
<p>需要设置gitee仓库的名称和仓库地址</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">url:</span> <span class="string">https://gitee.com/cmygis</span></span><br><span class="line"><span class="attr">root:</span> <span class="string">/myblog/</span></span><br><span class="line"><span class="comment"># ---------------------------------</span></span><br><span class="line"><span class="attr">deploy:</span></span><br><span class="line">  <span class="attr">type:</span> <span class="string">git</span></span><br><span class="line">  <span class="attr">repo:</span> <span class="string">https://gitee.com/cmygis/myblog</span> <span class="comment">#仓库地址</span></span><br><span class="line">  <span class="attr">branch:</span> <span class="string">master</span> <span class="comment">#仓库分支</span></span><br></pre></td></tr></table></figure>

<blockquote>
<p>hexo的配置文件有两个，一个是位于博客根目录的_config.yml，另一个是位于themes文件夹下对于主题目录下的——config.yml，是设置hexo主题的选项。</p>
</blockquote>
<h2 id="部署到远端"><a href="#部署到远端" class="headerlink" title="部署到远端"></a>部署到远端</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo d</span><br></pre></td></tr></table></figure>

<h2 id="hexo中文配置"><a href="#hexo中文配置" class="headerlink" title="hexo中文配置"></a>hexo中文配置</h2><p>修改博客文件夹下的_config.yml 的language :zh-CN</p>
<h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><ol>
<li><a target="_blank" rel="noopener" href="https://www.jianshu.com/p/3a05351a37dc">Hexo的Next主题详细配置</a></li>
<li><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_46036214/article/details/110137239">在Gitee搭建属于自己的博客_jiuqi_玖柒的博客-CSDN博客</a></li>
<li><a target="_blank" rel="noopener" href="https://blog.csdn.net/mqdxiaoxiao/article/details/93644533">Hexo博客NexT主题下添加分类、标签、关于菜单项_野猿新一-CSDN博客</a></li>
<li><a target="_blank" rel="noopener" href="https://hsinjhao.github.io/2019/05/16/BuildBlogsBasedOnHexoAndGithub/">利用hexo和github搭建个人博客的辛酸之路 | HsinJhao’s Blogs</a></li>
</ol>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="https://gitee.com/cmygis/2021/10/26/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/myblog/images/avatar.gif">
      <meta itemprop="name" content="矿小测">
      <meta itemprop="description" content="live and love">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="矿小测的博客">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/myblog/2021/10/26/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/" class="post-title-link" itemprop="url">并发编程</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2021-10-26 21:54:09" itemprop="dateCreated datePublished" datetime="2021-10-26T21:54:09+08:00">2021-10-26</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">更新于</span>
        <time title="修改时间：2021-10-31 22:13:33" itemprop="dateModified" datetime="2021-10-31T22:13:33+08:00">2021-10-31</time>
      </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h2 id="CountDownLatch"><a href="#CountDownLatch" class="headerlink" title="CountDownLatch"></a>CountDownLatch</h2><p>有以下两种使用场景</p>
<h3 id="场景1-让多个线程等待：模拟并发，让并发线程一起执行"><a href="#场景1-让多个线程等待：模拟并发，让并发线程一起执行" class="headerlink" title="场景1. 让多个线程等待：模拟并发，让并发线程一起执行"></a>场景1. 让多个线程等待：模拟并发，让并发线程一起执行</h3><p>CountDownLatch充当一个发令枪的角色</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">CountDownLatch countDownLatch = <span class="keyword">new</span> CountDownLatch(<span class="number">1</span>);</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">5</span>; i++) &#123;</span><br><span class="line">    <span class="keyword">new</span> Thread(() -&gt; &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">//准备完毕……运动员都阻塞在这，等待号令</span></span><br><span class="line">            countDownLatch.await();</span><br><span class="line">            String parter = <span class="string">&quot;【&quot;</span> + Thread.currentThread().getName() + <span class="string">&quot;】&quot;</span>;</span><br><span class="line">            System.out.println(parter + <span class="string">&quot;开始执行……&quot;</span>);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;).start();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">Thread.sleep(<span class="number">2000</span>);<span class="comment">// 裁判准备发令</span></span><br><span class="line">countDownLatch.countDown();<span class="comment">// 发令枪：执行发令</span></span><br></pre></td></tr></table></figure>

<p>运行结果：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">【Thread-0】开始执行……</span><br><span class="line">【Thread-1】开始执行……</span><br><span class="line">【Thread-4】开始执行……</span><br><span class="line">【Thread-3】开始执行……</span><br><span class="line">【Thread-2】开始执行……</span><br></pre></td></tr></table></figure>

<p>我们通过CountDownLatch.await()，让多个参与者线程启动后阻塞等待，然后在主线程 调用CountDownLatch.countdown(1) 将计数减为0，让所有线程一起往下执行；<br>以此实现了多个线程在同一时刻并发执行，来模拟并发请求的目的</p>
<h3 id="场景2-让单个线程等待-多个线程任务完成后，进行汇总合并"><a href="#场景2-让单个线程等待-多个线程任务完成后，进行汇总合并" class="headerlink" title="场景2 让单个线程等待:多个线程任务完成后，进行汇总合并"></a>场景2 让单个线程等待:多个线程任务完成后，进行汇总合并</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">CountDownLatch countDownLatch = <span class="keyword">new</span> CountDownLatch(<span class="number">5</span>);</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">5</span>; i++) &#123;</span><br><span class="line">    <span class="keyword">final</span> <span class="keyword">int</span> index = i;</span><br><span class="line">    <span class="keyword">new</span> Thread(() -&gt; &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            Thread.sleep(<span class="number">1000</span> + ThreadLocalRandom.current().nextInt(<span class="number">1000</span>));</span><br><span class="line">            System.out.println(<span class="string">&quot;finish&quot;</span> + index + Thread.currentThread().getName());</span><br><span class="line">            countDownLatch.countDown();</span><br><span class="line">        &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;).start();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">countDownLatch.await();<span class="comment">// 主线程在阻塞，当计数器==0，就唤醒主线程往下执行。</span></span><br><span class="line">System.out.println(<span class="string">&quot;主线程:在所有任务运行完成后，进行结果汇总&quot;</span>);</span><br></pre></td></tr></table></figure>

<p><strong>CountDownLatch的不足</strong></p>
<p>CountDownLatch是一次性的，计算器的值只能在构造方法中初始化一次，之后没有任何机制再次对其设置值，当CountDownLatch使用完毕后，它不能再次被使用。</p>
<h2 id="CyclicBarrier"><a href="#CyclicBarrier" class="headerlink" title="CyclicBarrier"></a>CyclicBarrier</h2><p><img src="https://img-blog.csdnimg.cn/img_convert/fa4d24955103ee1c8c0564ab45eebe26.png" alt="img"></p>
<h3 id="CountDownLatch与CyclicBarrier"><a href="#CountDownLatch与CyclicBarrier" class="headerlink" title="CountDownLatch与CyclicBarrier"></a><strong>CountDownLatch与CyclicBarrier</strong></h3><p>CountDownLatch和CyclicBarrier都能够实现线程之间的等待，只不过它们侧重点不同：</p>
<ul>
<li>CountDownLatch一般用于一个或多个线程，等待其他线程执行完任务后，再才执行</li>
<li>CyclicBarrier一般用于一组线程互相等待至某个状态，然后这一组线程再同时执行</li>
</ul>
<h2 id="Semaphore"><a href="#Semaphore" class="headerlink" title="Semaphore"></a>Semaphore</h2><p>Semaphore信号量，可以用来控制同时访问特定资源的线程数量，通过协调各个线程，以保证合理的使用资源。</p>
<p>例如停车场的车位，每有一辆车进入停车场，车位就会减1，每有一辆车从停车场出去，车位就增加1，当剩余车位为0时，停车场就不准车辆进入，直到有一辆车从停车场出去为止。</p>
<h3 id="使用场景："><a href="#使用场景：" class="headerlink" title="使用场景："></a>使用场景：</h3><p>用于资源有明确访问数量限制的场景，常用于限流。</p>
<p>比如：数据库连接池，同时进行连接的线程有数量限制，连接不能超过一定的数量，当连接达到限制数量后，后面的线程只能排队等待前面的线程释放了数据库连接。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">acquire()</span><br><span class="line">    获取一个令牌，在获取到令牌、或者被其他线程调用中断之前一直处于阻塞状态。</span><br><span class="line">acquire(<span class="keyword">int</span> permits)  </span><br><span class="line">获取一个令牌，在获取到令牌、或者被其他线程调用中断、或超时之前线程一直处于阻塞状态。</span><br><span class="line">    </span><br><span class="line">acquireUninterruptibly() </span><br><span class="line">获取一个令牌，在获取到令牌之前线程一直处于阻塞状态（忽略中断）。</span><br><span class="line">    </span><br><span class="line">tryAcquire()</span><br><span class="line">尝试获得令牌，返回获取令牌成功或失败，不阻塞线程。</span><br><span class="line">​</span><br><span class="line">tryAcquire(<span class="keyword">long</span> timeout, TimeUnit unit)</span><br><span class="line">尝试获得令牌，在超时时间内循环尝试获取，直到尝试获取成功或超时返回，不阻塞线程。</span><br><span class="line">​</span><br><span class="line">release()</span><br><span class="line">释放一个令牌，唤醒一个获取令牌不成功的阻塞线程。</span><br><span class="line">​</span><br><span class="line">hasQueuedThreads()</span><br><span class="line">等待队列里是否还存在等待线程。</span><br><span class="line">​</span><br><span class="line">getQueueLength()</span><br><span class="line">获取等待队列里阻塞的线程数。</span><br><span class="line">​</span><br><span class="line">drainPermits()</span><br><span class="line">清空令牌把可用令牌数置为<span class="number">0</span>，返回清空令牌的数量。</span><br><span class="line">​</span><br><span class="line">availablePermits()</span><br><span class="line">返回可用的令牌数量。</span><br></pre></td></tr></table></figure>



<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestCar</span> </span>&#123;</span><br><span class="line">    <span class="comment">//停车场同时容纳的车辆10</span></span><br><span class="line">    <span class="keyword">private</span>  <span class="keyword">static</span>  Semaphore semaphore=<span class="keyword">new</span> Semaphore(<span class="number">10</span>);</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="comment">//模拟100辆车进入停车场</span></span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;<span class="number">100</span>;i++)&#123;</span><br><span class="line">            Thread thread=<span class="keyword">new</span> Thread(<span class="keyword">new</span> Runnable() &#123;</span><br><span class="line">                <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> </span>&#123;</span><br><span class="line">                    <span class="keyword">try</span> &#123;</span><br><span class="line">                        System.out.println(<span class="string">&quot;====&quot;</span>+Thread.currentThread().getName()+<span class="string">&quot;来到停车场&quot;</span>);</span><br><span class="line">                        <span class="keyword">if</span>(semaphore.availablePermits()==<span class="number">0</span>)&#123;</span><br><span class="line">                            System.out.println(<span class="string">&quot;车位不足，请耐心等待&quot;</span>);</span><br><span class="line">                        &#125;</span><br><span class="line">                        semaphore.acquire();<span class="comment">//获取令牌尝试进入停车场</span></span><br><span class="line">                        System.out.println(Thread.currentThread().getName()+<span class="string">&quot;成功进入停车场&quot;</span>);</span><br><span class="line">                        Thread.sleep(<span class="keyword">new</span> Random().nextInt(<span class="number">10000</span>));<span class="comment">//模拟车辆在停车场停留的时间</span></span><br><span class="line">                        System.out.println(Thread.currentThread().getName()+<span class="string">&quot;驶出停车场&quot;</span>);</span><br><span class="line">                        semaphore.release();<span class="comment">//释放令牌，腾出停车场车位</span></span><br><span class="line">                    &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                        e.printStackTrace();</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;,i+<span class="string">&quot;号车&quot;</span>);</span><br><span class="line">            thread.start();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/98593407">https://zhuanlan.zhihu.com/p/98593407</a></p>
<p>释放令牌成功之后，将队列中的第一个需要唤醒的线程进行唤醒</p>
<h2 id="线程间交换数据Exchanger"><a href="#线程间交换数据Exchanger" class="headerlink" title="线程间交换数据Exchanger"></a><strong>线程间交换数据Exchanger</strong></h2><p>Exchanger是用于线程间数据交换的工具类<br>它提供一个同步点 ,在这个同步点两个线程可以通过exchange彼此交换数据<br>第一个线程先执行exchange()方法，它会一直等待第二个线程也<br>执行exchange方法，当两个线程都到达同步点时，这两个线程就可以交换数据，将本线程生产出来的数据传递给对方。<br>————————————————<br>版权声明：本文为CSDN博主「呆大王」的原创文章，遵循CC 4.0 BY-SA版权协议，转载请附上原文出处链接及本声明。<br>原文链接：<a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_50695280/article/details/115099872">https://blog.csdn.net/qq_50695280/article/details/115099872</a></p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> java.util.concurrent.Exchanger;</span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.ExecutorService;</span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.Executors;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ExchangerTest</span> </span>&#123;</span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> Exchanger&lt;String&gt; ex = <span class="keyword">new</span> Exchanger&lt;&gt;();</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        ExecutorService executorService = Executors.newCachedThreadPool();</span><br><span class="line">        executorService.execute(()-&gt; &#123;</span><br><span class="line">            String a = <span class="string">&quot;小红&quot;</span>;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                ex.exchange(a);</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">        executorService.execute(()-&gt; &#123;</span><br><span class="line">            String b = <span class="string">&quot;小明&quot;</span>;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                String exchange = ex.exchange(b);</span><br><span class="line">                System.out.println(<span class="string">&quot;得到了: &quot;</span>+exchange);</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;);</span><br><span class="line">        executorService.shutdown();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">-----------------------------------------</span><br><span class="line">输出：</span><br><span class="line">    得到了：小红</span><br></pre></td></tr></table></figure>



<h2 id="原子操作类"><a href="#原子操作类" class="headerlink" title="原子操作类"></a><strong>原子操作类</strong></h2><p><a target="_blank" rel="noopener" href="https://blog.csdn.net/weixin_30307921/article/details/98445676">https://blog.csdn.net/weixin_30307921/article/details/98445676</a></p>
<h2 id="乐观锁和悲观锁"><a href="#乐观锁和悲观锁" class="headerlink" title="乐观锁和悲观锁"></a>乐观锁和悲观锁</h2><h3 id="悲观锁"><a href="#悲观锁" class="headerlink" title="悲观锁"></a>悲观锁</h3><p>悲观锁：认为别的线程会修改值</p>
<p>独占锁是一种悲观锁，synchronized就是一种独占锁。synchronized加锁后能够确保程序执行时不会被其他线程干扰，得到正确的结果。</p>
<h3 id="乐观锁"><a href="#乐观锁" class="headerlink" title="乐观锁"></a>乐观锁</h3><p>乐观锁：认为别的线程不会去修改值。如果发现值被修改了，可以再次重试。CAS机制（Compare and Swap)就是一种乐观锁。</p>
<h2 id="CAS"><a href="#CAS" class="headerlink" title="CAS"></a>CAS</h2><p><code>CAS</code>是一种无锁（lock-free)算法。也是一种现代CPU广泛支持的CPU指令级的操作，只有一步原子操作，所以非常快。而且CAS避免了请求操作系统来裁定锁的问题，不用麻烦操作系统，直接走CPU内部就搞定了。</p>
<p><code>CAS</code>有三个操作参数：</p>
<ol>
<li>内存位置V(它的值是我们想要去更新的)</li>
<li>预期原值A(上一次从内存中读取的值)</li>
<li>新值B(应该写入的新值)</li>
</ol>
<p><code>CAS</code> 操作过程：将内存位置V的值与A比较(Compare)，如果相等，则说明没有其他线程来修改过这个值，所以把内存V的值更新成B(Swap)，如果不相等，说明V上的值被修改过了，不更新，而是返回当前V的值，再重新执行一次任务再继续这个过程。</p>
<p>所以，当多个线程尝试使用CAS同时更新同一个变量时，其中一个线程会成功更新变量的值，剩下的会失败。失败的线程可以重试或者什么也不做。</p>
<h2 id="JVM对CAS的支持"><a href="#JVM对CAS的支持" class="headerlink" title="JVM对CAS的支持"></a>JVM对CAS的支持</h2><p>在JDK1.5之前，如果不编写明确的代码就无法执行CAS操作，在JDK1.5中引入了底层的支持，在int、long、和对象的引用等类型上都公开了CAS的操作，并且JVM把他们编译为底层硬件提供的最有效的方法，在运行CAS的平台上，运行时把它们编译为相应的机器指令，如果处理器/CPU不支持CAS指令，那么JVM将使用自旋锁。</p>
<p>在原子类变量中，如java.util.concurrent.atomic包下的AtomicXXX，都使用了这些底层的JVM支持为数字类型的引用类型提供一种高效的CAS操作，而在java.util.concurrent中的大多数类在实现时都直接或间接的使用了这些原子变量类。</p>
<p>java.util.concurrent.atomic.AtomicLong源码中的自增getAndIncrement()方法：</p>
<h2 id="CAS缺点"><a href="#CAS缺点" class="headerlink" title="CAS缺点"></a>CAS缺点</h2><p>CAS虽然很高效的解决原子操作，但是CAS仍然存在三大问题。ABA问题，循环时间长开销大和只能保证一个共享变量的原子操作。</p>
<ol>
<li><p>ABA问题。因为CAS需要在操作值的时候检查下值有没有发生变化，如果没有发生变化则更新，但是如果一个值原来是A，变成了B，又变成了A，那么使用CAS进行检查时会发现它的值没有发生变化，但是实际上却变化了。ABA问题的解决思路就是使用版本号。在变量前面追加上版本号，每次变量更新的时候把版本号加一，那么A－B－A 就会变成1A-2B－3A。</p>
<p>从Java1.5开始JDK的atomic包里提供了一个类AtomicStampedReference来解决ABA问题。这个类的compareAndSet方法作用是首先检查当前引用是否等于预期引用，并且当前标志是否等于预期标志，如果全部相等，则以原子方式将该引用和该标志的值设置为给定的更新值。</p>
</li>
<li><p>循环时间长开销大。自旋CAS如果长时间不成功，会给CPU带来非常大的执行开销。如果JVM能支持处理器提供的pause指令那么效率会有一定的提升，pause指令有两个作用，第一它可以延迟流水线执行指令（de-pipeline）,使CPU不会消耗过多的执行资源，延迟的时间取决于具体实现的版本，在一些处理器上延迟时间是零。第二它可以避免在退出循环的时候因内存顺序冲突（memory order violation）而引起CPU流水线被清空（CPU pipeline flush），从而提高CPU的执行效率。</p>
</li>
<li><p>只能保证一个共享变量的原子操作。当对一个共享变量执行操作时，我们可以使用循环CAS的方式来保证原子操作，但是对多个共享变量操作时，循环CAS就无法保证操作的原子性，这个时候就可以用锁，或者有一个取巧的办法，就是把多个共享变量合并成一个共享变量来操作。比如有两个共享变量i＝2,j=a，合并一下ij=2a，然后用CAS来操作ij。从Java1.5开始JDK提供了AtomicReference类来保证引用对象之间的原子性，你可以把多个变量放在一个对象里来进行CAS操作。</p>
</li>
<li><p>比较花费CPU资源，即使没有任何争用也会做一些无用功。</p>
</li>
<li><p>会增加程序测试的复杂度，稍不注意就会出现问题。</p>
</li>
</ol>
<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>可以用CAS在无锁的情况下实现原子操作，但要明确应用场合，非常简单的操作且又不想引入锁可以考虑使用CAS操作，当想要非阻塞地完成某一操作也可以考虑CAS。不推荐在复杂操作中引入CAS，会使程序可读性变差，且难以测试，同时会出现ABA问题。</p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>





</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">


<div class="copyright">
  &copy; 
  <span itemprop="copyrightYear">2021</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">矿小测</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.js.org/" rel="noopener" target="_blank">NexT.Gemini</a> 强力驱动
  </div>

    </div>
  </footer>

  
  <script src="https://cdn.jsdelivr.net/npm/animejs@3.2.1/lib/anime.min.js" integrity="sha256-XL2inqUJaslATFnHdJOi9GfQ60on8Wx1C2H8DYiN1xY=" crossorigin="anonymous"></script>
<script src="/myblog/js/comments.js"></script><script src="/myblog/js/utils.js"></script><script src="/myblog/js/motion.js"></script><script src="/myblog/js/next-boot.js"></script>

  





  





</body>
</html>
